import javax.swing.*;

import ds.MyTree;
import ds.SkillTree;

import java.awt.*;
import java.awt.event.*;

public class GamePanel extends JPanel implements ActionListener, KeyListener {
    private Timer timer;
    private Map map;
    private Pacman pacman;
    private java.util.List<Ghost> ghosts = new java.util.ArrayList<>();
    private UndoStack undoStack;
    private Leaderboard leaderboard;
    private SkillTree skillTree;
    private int ghostMoveCounter = 0;
    private int ghostMoveInterval = 3; // 幽灵每3帧移动一次
    private boolean gameOver = false;
    private int score = 0;

    public GamePanel() {
        setFocusable(true);
        setBackground(Color.BLACK);
        setPreferredSize(new Dimension(800, 900));
        addKeyListener(this);
        map = new Map();
        pacman = new Pacman(1, 1);
        ghosts.add(new Ghost(10, 10, "images/ghost1.png"));
        ghosts.add(new Ghost(10, 9, "images/ghost2.png"));
        ghosts.add(new Ghost(11, 10, "images/ghost3.png"));
        ghosts.add(new Ghost(11, 9, "images/ghost4.png"));
        undoStack = new UndoStack();
        leaderboard = new Leaderboard();
        skillTree = new SkillTree();
        // 遍历MyTree并打印所有技能名（示例）
        java.util.List<SkillTree.Skill> allSkills = skillTree.getTree().traverse();
        for (SkillTree.Skill skill : allSkills) {
            System.out.println("技能树节点: " + skill.name);
        }
        timer = new Timer(100, this);
        timer.start();
    }

    @Override
    public void paintComponent(Graphics g) {
        super.paintComponent(g);
        map.draw(g);
        pacman.draw(g);
        for (Ghost ghost : ghosts) {
            ghost.draw(g);
        }
        drawScoreAndRank(g);
        drawSkillTree(g);
    }

    private void drawScoreAndRank(Graphics g) {
        int startX = Map.COLS * Map.TILE_SIZE + 30;
        int y = 80;
        g.setColor(Color.WHITE);
        g.setFont(new Font("Arial", Font.BOLD, 22));
        g.drawString("得分: " + score, startX, y);
        y += 40;
        // 计算当前分数的名次
        int rank = 1;
        int total = leaderboard.getScores().length;
        int[] scores = leaderboard.getScores();
        for (int i = 0; i < scores.length; i++) {
            if (score < scores[i]) rank++;
        }
        g.setFont(new Font("Arial", Font.PLAIN, 18));
        g.drawString("当前名次: 第" + rank + "名/共" + (total + 1) + "人", startX, y);
    }

    private void drawSkillTree(Graphics g) {
        int panelWidth = getWidth();
        int mapWidth = Map.COLS * Map.TILE_SIZE;
        int rightPanelWidth = panelWidth - mapWidth;
        int nodeSize = 40;
        int minGap = 24;
        MyTree.Node root = skillTree.getTree().getRoot();
        int treeWidth = getSubtreeWidth(root, nodeSize, minGap);
        int startX = mapWidth + (rightPanelWidth - treeWidth) / 2;
        int startY = 200;
        g.setFont(new Font("微软雅黑", Font.BOLD, 18));
        g.setColor(Color.WHITE);
        g.drawString("技能树", startX + treeWidth/2 - 30, startY - 40);
        drawSkillTreeNodeSmart((Graphics2D)g, root, startX + treeWidth/2, startY, nodeSize, minGap);
        // 列出所有技能和最强技能（叶子节点）
        java.util.List<SkillTree.Skill> allSkills = skillTree.getTree().traverse();
        int treeHeight = skillTree.getTree().getDepth() * 60; // 估算树结构高度
        int listStartY = startY + treeHeight + 40;
        int nodeCount = skillTree.getTree().getNodeCount();
        int leafCount = skillTree.getTree().getLeafCount();
        java.util.List<SkillTree.Skill> leafSkills = new java.util.ArrayList<>();
        for (SkillTree.Skill skill : allSkills) {
            MyTree.Node node = findNode(skillTree.getTree().getRoot(), skill);
            if (node != null && node.left == null && node.right == null) {
                leafSkills.add(skill);
            }
        }
        g.setFont(new Font("微软雅黑", Font.PLAIN, 14));
        g.setColor(Color.CYAN);
        // 所有技能按列显示
        g.drawString("所有技能（共" + nodeCount + "个）：", startX, listStartY);
        int y = listStartY + 24;
        for (SkillTree.Skill skill : allSkills) {
            g.drawString(skill.name, startX, y);
            y += 20;
        }
        // 最强技能（叶子节点）按列显示
        g.drawString("最强技能（共" + leafCount + "个）：", startX, y + 10);
        y += 34;
        for (SkillTree.Skill skill : leafSkills) {
            g.drawString(skill.name, startX, y);
            y += 20;
        }
    }

    // 递归计算每个子树的实际宽度
    private int getSubtreeWidth(MyTree.Node node, int nodeSize, int minGap) {
        if (node == null) return 0;
        if (node.left == null && node.right == null) return nodeSize;
        int leftWidth = getSubtreeWidth(node.left, nodeSize, minGap);
        int rightWidth = getSubtreeWidth(node.right, nodeSize, minGap);
        if (leftWidth == 0) leftWidth = nodeSize;
        if (rightWidth == 0) rightWidth = nodeSize;
        return leftWidth + rightWidth + minGap;
    }

    // 自适应宽度递归绘制技能树
    private void drawSkillTreeNodeSmart(Graphics2D g, MyTree.Node node, int x, int y, int nodeSize, int minGap) {
        if (node == null) return;
        int leftWidth = getSubtreeWidth(node.left, nodeSize, minGap);
        int rightWidth = getSubtreeWidth(node.right, nodeSize, minGap);
        // 画连线和递归画子节点
        if (node.left != null) {
            int childX = x - (rightWidth + minGap) / 2;
            g.setColor(new java.awt.Color(120,255,180));
            g.setStroke(new java.awt.BasicStroke(3));
            g.drawLine(x + nodeSize/2, y + nodeSize, childX + nodeSize/2, y + 60);
            drawSkillTreeNodeSmart(g, node.left, childX, y + 60, nodeSize, minGap);
        }
        if (node.right != null) {
            int childX = x + (leftWidth + minGap) / 2;
            g.setColor(new java.awt.Color(120,255,180));
            g.setStroke(new java.awt.BasicStroke(3));
            g.drawLine(x + nodeSize/2, y + nodeSize, childX + nodeSize/2, y + 60);
            drawSkillTreeNodeSmart(g, node.right, childX, y + 60, nodeSize, minGap);
        }
        // 画节点
        drawSkillNode(g, node.val, x, y, nodeSize);
    }

    private void drawSkillNode(Graphics2D g, SkillTree.Skill skill, int x, int y, int size) {
        if (skill.unlocked) g.setColor(new java.awt.Color(100, 200, 255));
        else g.setColor(new java.awt.Color(60, 60, 60));
        g.fillRoundRect(x, y, size, size, 20, 20);
        g.setColor(Color.WHITE);
        g.setStroke(new java.awt.BasicStroke(3));
        g.drawRoundRect(x, y, size, size, 20, 20);
        if (skill.iconPath != null) {
            java.awt.Image img = java.awt.Toolkit.getDefaultToolkit().getImage(skill.iconPath);
            g.drawImage(img, x+8, y+8, size-16, size-16, null);
        }
        g.setColor(Color.WHITE);
        g.setFont(new Font("微软雅黑", Font.BOLD, 14));
        java.awt.FontMetrics fm = g.getFontMetrics();
        int textWidth = fm.stringWidth(skill.name);
        g.drawString(skill.name, x + (size-textWidth)/2, y + size + 18);
        if (skill.maxLevel > 1) {
            g.setFont(new Font("Arial", Font.PLAIN, 12));
            g.drawString("Lv " + skill.level + "/" + skill.maxLevel, x+size-38, y+size-8);
        }
    }

    @Override
    public void actionPerformed(ActionEvent e) {
        if (gameOver) return;
        // 幽灵每ghostMoveInterval帧才移动一次
        ghostMoveCounter++;
        if (ghostMoveCounter >= ghostMoveInterval) {
            for (int i = 0; i < ghosts.size(); i++) {
                Ghost ghost = ghosts.get(i);
                int targetRow = pacman.getRow();
                int targetCol = pacman.getCol();
                if (i == 1) { // 粉色，追Pacman前方4格
                    int[] front = pacman.getFront(4, map);
                    targetRow = front[0];
                    targetCol = front[1];
                } else if (i == 2) { // 蓝色，追Pacman和红幽灵的中点
                    Ghost red = ghosts.get(0);
                    targetRow = (pacman.getRow() + red.row) / 2;
                    targetCol = (pacman.getCol() + red.col) / 2;
                } else if (i == 3) { // 橙色，远追Pacman，近追左下角
                    int dist = Math.abs(ghost.row - pacman.getRow()) + Math.abs(ghost.col - pacman.getCol());
                    if (dist > 8) {
                        targetRow = pacman.getRow();
                        targetCol = pacman.getCol();
                    } else {
                        targetRow = map.getRows() - 2;
                        targetCol = 1;
                    }
                }
                ghost.moveBFS(map, targetRow, targetCol);
            }
            ghostMoveCounter = 0;
        }
        // 检查Pacman是否被幽灵吃掉
        for (Ghost ghost : ghosts) {
            if (ghost.row == pacman.getRow() && ghost.col == pacman.getCol()) {
                gameOver = true;
                timer.stop();
                showGameOverDialog();
                break;
            }
        }
        repaint();
    }

    @Override
    public void keyPressed(KeyEvent e) {
        if (gameOver) return;
        if (e.getKeyCode() == KeyEvent.VK_Z) {
            int[] pos = undoStack.pop();
            if (pos != null) {
                pacman.setPosition(pos[0], pos[1]);
                repaint();
            }
        } else {
            pacman.setDirection(e.getKeyCode());
            // Pacman每次按键只移动一步
            undoStack.push(pacman.getRow(), pacman.getCol());
            int oldRow = pacman.getRow();
            int oldCol = pacman.getCol();
            boolean ateDot = pacman.move(map);
            if (pacman.getRow() != oldRow || pacman.getCol() != oldCol) {
                repaint();
            }
            // 检查Pacman是否被幽灵吃掉
            for (Ghost ghost : ghosts) {
                if (ghost.row == pacman.getRow() && ghost.col == pacman.getCol()) {
                    gameOver = true;
                    timer.stop();
                    showGameOverDialog();
                    break;
                }
            }
            repaint();
        }
    }

    @Override
    public void keyReleased(KeyEvent e) {}
    @Override
    public void keyTyped(KeyEvent e) {}

    private void showGameOverDialog() {
        SwingUtilities.invokeLater(() -> {
            int option = JOptionPane.showOptionDialog(this,
                    "游戏结束！你被幽灵吃掉了。",
                    "游戏结束",
                    JOptionPane.DEFAULT_OPTION,
                    JOptionPane.INFORMATION_MESSAGE,
                    null,
                    new Object[]{"重新开始", "退出"},
                    "重新开始");
            if (option == 0) {
                restartGame();
            } else {
                System.exit(0);
            }
        });
    }

    private void restartGame() {
        // 重新初始化游戏状态
        leaderboard.addScore(score); // 游戏结束时保存分数
        score = 0;
        map = new Map();
        pacman = new Pacman(1, 1);
        ghosts.clear();
        ghosts.add(new Ghost(10, 10, "images/ghost1.png"));
        ghosts.add(new Ghost(10, 9, "images/ghost2.png"));
        ghosts.add(new Ghost(11, 10, "images/ghost3.png"));
        ghosts.add(new Ghost(11, 9, "images/ghost4.png"));
        undoStack = new UndoStack();
        skillTree = new SkillTree();
        ghostMoveCounter = 0;
        gameOver = false;
        timer.start();
        repaint();
    }

    // 新增辅助方法：根据技能查找节点
    private MyTree.Node  findNode(MyTree.Node node, SkillTree.Skill skill) {
        if (node == null) return null;
        if (node.val == skill) return node;
        MyTree.Node left = findNode(node.left, skill);
        if (left != null) return left;
        return findNode(node.right, skill);
    }
} 